package com.hightrast.service.compareToData;

import com.hightrast.service.compareToData.stage.EntityComparator;
import com.hightrast.service.compareToData.stage.EntityUpdater;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
public class EntitySynchronizer {

    /**
     * 同步新旧实体列表
     *
     * @param newEntities    新数据列表
     * @param oldEntities    旧数据列表
     * @param idExtractor    ID 提取器
     * @param updateFunction 更新操作
     * @param saveFunction   新增操作
     * @param deleteFunction 删除操作
     * @param comparator     比较策略
     * @param updater        更新策略
     * @param <T>            实体类型
     */
    public static <T> void syncEntities(List<T> newEntities,
                                        List<T> oldEntities,
                                        Function<T, Long> idExtractor,
                                        Consumer<List<T>> updateFunction,
                                        Consumer<List<T>> saveFunction,
                                        Consumer<List<Long>> deleteFunction,
                                        EntityComparator<T> comparator,
                                        EntityUpdater<T> updater) {

        if (newEntities == null || idExtractor == null || comparator == null || updater == null) {
            return;
        }
        if (saveFunction != null && (oldEntities == null || oldEntities.isEmpty())) {
            saveFunction.accept(newEntities);
            return;
        }
        ConcurrentHashMap<Long, T> oldEntitiesMap = oldEntities.stream()
                .collect(Collectors.toConcurrentMap(
                        idExtractor,
                        Function.identity(),
                        (v1, v2) -> v2,
                        ConcurrentHashMap::new
                ));
        List<T> entitiesToUpdate = new ArrayList<>(newEntities.size());
        List<T> entitiesToAdd = new ArrayList<>(newEntities.size());

        for (T newEntity : newEntities) {
            Long newEntityId = idExtractor.apply(newEntity);
            T oldEntity = oldEntitiesMap.get(newEntityId);
            if (oldEntity != null) {
                if (!comparator.areEqual(newEntity, oldEntity)) {
                    // 更新数据
                    updater.updateEntity(oldEntity, newEntity);
                    entitiesToUpdate.add(oldEntity);
                }
                // 删除原数据
                oldEntitiesMap.remove(newEntityId);
            } else {
                // 新增数据
                entitiesToAdd.add(newEntity);
            }
        }

        // 删除数据
        List<Long> idsToDelete = new ArrayList<>(oldEntitiesMap.keySet());
        if (deleteFunction != null && !idsToDelete.isEmpty()) {
            deleteFunction.accept(idsToDelete);
        }

        // 更新数据
        if (updateFunction != null && !entitiesToUpdate.isEmpty()) {
            updateFunction.accept(entitiesToUpdate);
        }

        // 新增数据
        if (saveFunction != null && !entitiesToAdd.isEmpty()) {
            saveFunction.accept(entitiesToAdd);
        }
    }
}